
# 函数式计算机语言模块化设计不可或缺的一部分
# 函数参数
# 默认为位置参数，可能函数太多会出现传参错误
# 关键字参数，实现一一对应的键值，确实传参正确
# Python参数规定，位置参数必须在关键字参数之前
# 默认值参数，如果没有传入该参数，函数会使用默认值
# 不成文的规定，如果使用默认值参数，在设计函数时应该把默认值参数放置在最后面

def sum1(a, /, b, c):
    pass
# 斜杠左边的参数只能是位置参数，不能是关键字参数
def sum2(a, *, b, c):
    pass
# *号右边的参数只能是关键字参数

# 搜集函数
def souji(*args):
    pass
# 无论传入多少个参数，都是一一对其使用，内部其实就是相当于传入了一个元组，可以在函数体内直接使用下标访问
# 元组能够进行打包
# 函数解包，一一对应收集
# 除了元组，函数还可以将传入的参数打包成字典
def zidian(**kwargs):
    pass
# 传入关键字参数，将关键字和values打包成一个字典
# 在使用args搜集参数时，搜集参数在前面，后面的只能使用关键字参数传值

# 解包参数
# 当我们需要传入的值原本是元组或者列表时
# 不能够直接传入函数-函数不会接受列表或者字典的形式的参数
# 因此我们需要进行解包操作
list1 = [1,2,3,4]
dict1 = {"关羽":"关云长"}
print(dict1)
# souji(*list1)
# zidian(**dict1)

# 函数作用域
# 函数内部定义global 全局变量名
# Python函数内部是无法修改全局变量的值的，需要声明global

# 嵌套函数
# 在函数内部定义的函数，只能在定义该函数的函数中使用该函数
# 上述情况我们可以将内部定义的函数作为外部函数的返回值
# 意义上就是进行函数指针

# 闭包-嵌套函数外部函数具有记忆
def power(exp):
    def exp_of(base):
        return exp ** base
    return exp_of
square = power(2)
cute = power(3)
print(square(2))
print(cute(2))
# 实现的是square是2次方，cute是3次方
# 闭包的意义，就是外部函数返回内部函数的引用，内部函数在被定义的时候会被记住初始赋的外部函数初值
# 例如上个例子的exp，在内部函数中引用nonlocal，使得外部函数定义的值可以在内部函数中发生修改
# 从而形成一个带有记忆且能够实时更新数据的函数

# 装饰器
# 函数作为参数传递
# @外部函数名
# 然后在后面定义我们需要传入的内部函数（这个函数是作为参数传递到外部函数中去的）
# 最后，实现了之后直接调用装饰器下面定义的这个函数的名称就能够实现闭包的一系列操作
# 给装饰器传递参数

# lambda表达式——匿名函数
# lambda arg1,arg2,arg3,arg4 : expression
# 左边是传入的参数，右边是表达式，也是返回值
mapped = list(map(lambda x:ord(x) + 10,"false"))
print(mapped)

# 生成器
# 使用yield修饰，函数会记住这个被修饰的东西，外部调用该函数会返回一个生成器
# 生成器中包含的是不同的功能值
# 生成器只支持next(),不支持下标访问

# 开发手册和函数文档
# 函数文档-函数文档一般写在函数的最上面
# 类型注释
def times(s:str,n:int) -> str:
    return s * n
# 这个代表作者希望我们传入的函数第一个参数类型是str,第二个参数类型是int,然后就是返回值是str
